#pragma once
#include <cstring>
#include <string>
#include <vector>
#include <algorithm>
#include <assert.h>

using namespace std;

class BigInteger
{
	typedef unsigned char byte;
public:
	BigInteger(void);
	BigInteger(__int64 value);
	BigInteger(unsigned __int64 value);
	BigInteger(const BigInteger &bi);
	BigInteger(string value, int radix);
	BigInteger(byte inData[], int inLen);
	BigInteger(unsigned int inData[], int inLen);
	BigInteger operator =(const BigInteger &bi2);
	BigInteger operator +(const BigInteger &bi2);
	BigInteger operator -();
	BigInteger modPow(BigInteger exp, BigInteger n);
	int bitCount();
	BigInteger BarrettReduction(BigInteger x, BigInteger n, BigInteger constant);
	bool operator >=(BigInteger bi2)
	{
		return ((*this) == bi2 || (*this) > bi2);
	}
	bool operator >(BigInteger bi2);
	bool operator ==(BigInteger bi2);
	BigInteger operator %(BigInteger bi2);
	void singleByteDivide(BigInteger &bi1, BigInteger &bi2,
		BigInteger &outQuotient, BigInteger &outRemainder);
	void multiByteDivide(BigInteger &bi1, BigInteger &bi2,
		BigInteger &outQuotient, BigInteger &outRemainder);
	int shiftRight(unsigned int buffer[], int bufLen, int shiftVal);
	BigInteger operator <<(int shiftVal);
	int shiftLeft(unsigned int buffer[], int bufLen, int shiftVal);
	bool operator <(BigInteger bi2);
	BigInteger operator +=(BigInteger bi2);
	BigInteger operator /(BigInteger bi2);
	BigInteger operator -=(BigInteger bi2);
	BigInteger operator -(BigInteger bi2);
	string DecToHex(unsigned int value, string format);
	string ToHexString();
	vector<byte> ToBytes();
	static byte htoi(const char *str);
public:
	~BigInteger(void);
public:
	BigInteger operator *(BigInteger bi2);
private:

public:
	static const int primesBelow2000[];
		// primes smaller than 2000 to test the generated prime number
	int dataLength;
		// number of actual chars used
private:
	static const int maxLength;
		// maximum length of the BigInteger in uint (4 bytes)
		// change this to suit the required level of precision.
	unsigned int *data;
		// stores bytes from the Big Integer
};
